/**
 * 
 */
package org.stars.util.jar;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.regex.Pattern;

import org.stars.util.StringUtility;
 
/**
 *	Classe di utilità per recuperare l'elenco completo o parziale dei jar
 *	caricati dal classloader.
 *
 * @author Francesco Benincasa (908099)
 * @date 11/nov/07, 23:26:32
 *
 */
public abstract class JarUtility {
	
	/**
	 * pezzo di regular expression da aggiungere al matcher
	 */
	protected static String regEx="([^\\\\]*)";
	
	/**
	 * Recupera l'intero elenco dei jar che entrano nel classpath attualmente 
	 * impiegato. 
	 * 
	 * @param namePattern
	 * 		pattern da applicare al nome del jar. 
	 * 
	 * @return
	 * 		arraylist del nome compreso il path di tutti i jar
	 */
	public static ArrayList<String> getListOfJar(String namePattern) {		
		namePattern=StringUtility.nvl(namePattern).toLowerCase();		
		namePattern=StringUtility.replace(namePattern,"*", regEx);
		if (!namePattern.endsWith(".jar"))
		namePattern=namePattern+".jar";
		
		Pattern jarPattern=Pattern.compile(namePattern,
				Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);			
		
		ArrayList<String> ret = new ArrayList<String>();
		ClassLoader loader = Thread.currentThread().getContextClassLoader();

		// If it's not a URLClassLoader, we can't deal with it!
		if (!(loader instanceof URLClassLoader)) {
			System.out
					.println("The current ClassLoader is not castable to a URLClassLoader. ClassLoader "
							+ "is of type ["
							+ loader.getClass().getName()
							+ "].");
			return ret;
		} else {
			Collection<URL> urls = new HashSet<URL>();
			while (loader != null) {
				try {
					URLClassLoader urlLoader = (URLClassLoader) loader;
					urls.addAll(Arrays.asList(urlLoader.getURLs()));
				} catch (Exception e) { /* Do nothing */
				}
				loader = loader.getParent();
			}

			for (URL url : urls) {
				String path = url.getFile();
				try {
					path = URLDecoder.decode(path, "UTF-8");
				} catch (UnsupportedEncodingException e) {
					/*
					 * UTF-8 is a required encoding
					 */}
				File location = new File(path);

				// Manage what happens when Resin decides to return URLs
				// that do not
				// match reality! For whatever reason, Resin decides to
				// return some JAR
				// URLs with an extra '!/' on the end of the jar file name
				// and a file:
				// in front even though that's the protocol spec, not the
				// path!
				if (!location.exists()) {
					if (path.endsWith("!/"))
						path = path.substring(0, path.length() - 2);
					if (path.startsWith("file:"))
						path = path.substring(5);
					location = new File(path);
				}

				if (!location.isDirectory()) {
					// stiamo parlando di un jar, lo gestiamo e lo inseriamo
					// nell'elenco dei file trovati
					if (jarPattern.matcher(location.toString()).find())
					{
						ret.add(location.toString());
					}
                }
				
			}

			return ret;
		}
	}
	
	/**
	 * Carica l'elenco completo dei jar presenti nel classpath.
	 * 
	 * @return
	 * 		arraylist del nome compreso il path di tutti i jar
	 */
	public static ArrayList<String> getListOfJar()
	{
		return getListOfJar(null);
	}
}
